package cn.o.app.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.widget.EditText;

@SuppressWarnings("deprecation")
public class OUtil {

	// 转换为弧度
	public static final double TO_RADIAN = Math.PI / 180;
	// 转换为角度
	public static final double TO_DEGRESS = 180 / Math.PI;

	public static SharedPreferences getPref(Context context, String fileName) {
		return context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
	}

	public static String getPrefString(Context context, String fileName,
			String key, String defValue) {
		return getPref(context, fileName).getString(key, defValue);
	}

	public static boolean setPrefString(Context context, String fileName,
			String key, String value) {
		Editor editor = getPref(context, fileName).edit();
		editor.putString(key, value);
		return editor.commit();
	}

	public static boolean getPrefBoolean(Context context, String fileName,
			String key, boolean defValue) {
		return getPref(context, fileName).getBoolean(key, defValue);
	}

	public static boolean setPrefBoolean(Context context, String fileName,
			String key, Boolean value) {
		Editor editor = getPref(context, fileName).edit();
		editor.putBoolean(key, value);
		return editor.commit();
	}

	public static int getPrefInt(Context context, String fileName, String key,
			int defValue) {
		return getPref(context, fileName).getInt(key, defValue);
	}

	public static boolean setPrefInt(Context context, String fileName,
			String key, int value) {
		Editor editor = getPref(context, fileName).edit();
		editor.putInt(key, value);
		return editor.commit();
	}

	public static long getPrefLong(Context context, String fileName,
			String key, long defValue) {
		return getPref(context, fileName).getLong(key, defValue);
	}

	public static boolean setPrefLong(Context context, String fileName,
			String key, long value) {
		Editor editor = getPref(context, fileName).edit();
		editor.putLong(key, value);
		return editor.commit();
	}

	public static float getPrefFloat(Context context, String fileName,
			String key, float defValue) {
		return getPref(context, fileName).getFloat(key, defValue);
	}

	public static boolean setPrefFloat(Context context, String fileName,
			String key, float value) {
		Editor editor = getPref(context, fileName).edit();
		editor.putFloat(key, value);
		return editor.commit();
	}

	public static double getPrefDouble(Context context, String fileName,
			String key, double defValue) {
		String doubleStr = getPrefString(context, fileName, key, "");
		if (doubleStr.isEmpty()) {
			return defValue;
		}
		try {
			return Double.parseDouble(doubleStr);
		} catch (Exception e) {
			return defValue;
		}
	}

	public static boolean setPrefDouble(Context context, String fileName,
			String key, double value) {
		return setPrefString(context, fileName, key, value + "");
	}

	public static String getAppVersionName(Context context) {
		try {
			PackageInfo manager = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			return manager.versionName;
		} catch (NameNotFoundException e) {
			return "";
		}
	}

	public static String getAppPackage(Context context) {
		return context.getPackageName();
	}

	public static float getRawSize(Context context, int unit, float size) {
		return TypedValue.applyDimension(
				unit,
				size,
				(context == null ? Resources.getSystem() : context
						.getResources()).getDisplayMetrics());
	}

	public static float dp2px(Context context, float size) {
		return TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP,
				size,
				(context == null ? Resources.getSystem() : context
						.getResources()).getDisplayMetrics());
	}

	public static float sp2px(Context context, float size) {
		return TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_SP,
				size,
				(context == null ? Resources.getSystem() : context
						.getResources()).getDisplayMetrics());
	}

	// 转换为小写字母的MD5，如果需要大写请调用toUpperCase()方法
	public static String md5(String text) {
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(text.getBytes());
			return new BigInteger(1, md5.digest()).toString(16);
		} catch (Exception e) {
			return "";
		}
	}

	public static <T> ArrayList<T> asArrayList(T[] array) {
		ArrayList<T> arrayList = new ArrayList<T>();
		if (array == null) {
			return arrayList;
		}
		for (int i = 0, size = array.length; i < size; i++) {
			arrayList.add(array[i]);
		}
		return arrayList;
	}

	public static boolean compress(String sourceImage) {
		return compress(sourceImage, sourceImage);
	}

	public static boolean compress(String sourceImage, String destImage) {
		return compress(sourceImage, destImage, 0, 0);
	}

	public static boolean compress(String sourceImage, int expectWidth,
			int expectHeight) {
		return compress(sourceImage, sourceImage, expectWidth, expectHeight);
	}

	public static boolean compress(String sourceImage, String destImage,
			int expectWidth, int expectHeight) {
		try {
			BitmapFactory.Options opts = new BitmapFactory.Options();
			opts.inJustDecodeBounds = true;
			BitmapFactory.decodeFile(sourceImage, opts);
			if (expectWidth > 0 && expectHeight > 0) {
				float width = opts.outWidth;
				float height = opts.outHeight;
				float scaleX = 1;
				float scaleY = 1;
				if (width < height) {
					if (expectWidth < expectHeight) {
						scaleX = expectWidth / width;
						scaleY = expectHeight / height;
					} else {
						scaleX = expectHeight / width;
						scaleY = expectWidth / height;
					}
				} else {
					if (expectWidth < expectHeight) {
						scaleX = expectWidth / height;
						scaleY = expectHeight / width;
					} else {
						scaleX = expectHeight / height;
						scaleY = expectWidth / width;
					}
				}
				float scale = scaleX < scaleY ? scaleX : scaleY;
				if (scale < 1) {
					opts.inSampleSize = (int) (1 / scale + 0.5f);
				}
			}
			opts.inJustDecodeBounds = false;
			opts.inInputShareable = true;
			opts.inPurgeable = true;
			Bitmap bitmap = BitmapFactory.decodeFile(sourceImage, opts);
			FileOutputStream fos = new FileOutputStream(destImage);
			bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
			bitmap.recycle();
			fos.flush();
			fos.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	public static byte[] bitmap2ByteArray(Bitmap bitmap) {
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
			byte[] bytes = baos.toByteArray();
			baos.close();
			return bytes;
		} catch (Exception e) {
			return null;
		}
	}

	public static String getDiskCacheDir(Context context, String dirName) {
		String cachePath = null;
		if (Environment.MEDIA_MOUNTED.equals(Environment
				.getExternalStorageState())) {
			File externalCacheDir = context.getExternalCacheDir();
			if (externalCacheDir != null) {
				cachePath = externalCacheDir.getPath();
			}
		}
		if (cachePath == null) {
			File cacheDir = context.getCacheDir();
			if (cacheDir != null && cacheDir.exists()) {
				cachePath = cacheDir.getPath();
			}
		}
		cachePath = cachePath + File.separator + dirName;
		File cacheFile = new File(cachePath);
		if (!cacheFile.exists()) {
			if (!cacheFile.mkdirs()) {
				return null;
			}
		}
		return cacheFile.getPath();
	}

	public static String getDiskCacheRandomFile(Context context, String prefix,
			String suffix) {
		String cacheDir = getDiskCacheDir(context, "OApp");
		if (cacheDir == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		sb.append(cacheDir);
		sb.append(File.separator);
		if (prefix != null) {
			sb.append(prefix);
		}
		sb.append(UUID.randomUUID().toString().replace("-", ""));
		if (suffix != null) {
			sb.append(suffix);
		}
		return sb.toString();
	}

	public static String getDiskCacheRandomJpg(Context context) {
		return getDiskCacheRandomFile(context, "IMG_", ".jpg");
	}

	// 根据经纬度计算距离
	public static double getDistance(double latitudeA, double longitudeA,
			double latitudeB, double longitudeB) {
		double radianLatitudeA = latitudeA * TO_RADIAN;
		double radianLatitudeB = latitudeB * TO_RADIAN;
		double radianLatidueDistance = radianLatitudeA - radianLatitudeB;
		double radianLongitudeDistance = (longitudeA - longitudeB) * TO_RADIAN;
		return 6378137 * 2 * Math.asin(Math.sqrt(Math.pow(
				Math.sin(radianLatidueDistance * 0.5), 2)
				+ Math.cos(radianLatitudeA)
				* Math.cos(radianLatitudeB)
				* Math.pow(Math.sin(radianLongitudeDistance * 0.5), 2)));
	}

	public static int getYear(Date date) {
		return date.getYear() + 1900;
	}

	public static int getMonth(Date date) {
		return date.getMonth() + 1;
	}

	public static int getDay(Date date) {
		return date.getDate();
	}

	// 闰年
	public static boolean isLeap(Date date) {
		int year = date.getYear() + 1900;
		return isLeap(year);
	}

	// 闰年
	public static boolean isLeap(int year) {
		return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
	}

	public static int getDaysOfMonth(Date date) {
		return getDaysOfMonth(OUtil.getYear(date), OUtil.getMonth(date));
	}

	public static Date getDate(int year, int month, int day) {
		return new Date(year - 1900, month - 1, day);
	}

	public static Date getDate(int year, int month, int day, int hour,
			int minute) {
		return new Date(year - 1900, month - 1, day, hour, minute);
	}

	public static int getDaysOfMonth(int year, int month) {
		if (month == 2) {
			return isLeap(year) ? 29 : 28;
		} else if (month == 4 || month == 6 || month == 9 || month == 11) {
			return 30;
		} else {
			return 31;
		}
	}

	public static boolean isSameDay(Date d1, Date d2) {
		return (d1 != null && d2 != null) ? (d1.getYear() == d2.getYear()
				&& d1.getMonth() == d2.getMonth() && d1.getDate() == d2
				.getDate()) : (d1 == d2);
	}

	public static boolean isEmpty(String str) {
		return str == null ? true : str.isEmpty();
	}

	public static TextWatcher setEditTextDecimals(EditText editText,
			int decimals) {
		EditTextDecimalsTextWatcher watcher = new EditTextDecimalsTextWatcher();
		watcher.setEditText(editText);
		watcher.setDecimals(decimals);
		editText.addTextChangedListener(watcher);
		return watcher;
	}

	public static class EditTextDecimalsTextWatcher implements TextWatcher {
		protected EditText mEditText;

		protected int mDecimals;

		protected boolean catchChanged;

		public void setEditText(EditText editText) {
			mEditText = editText;
		}

		public void setDecimals(int decimals) {
			mDecimals = decimals;
		}

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
		}

		@Override
		public void afterTextChanged(Editable s) {
			if (catchChanged) {
				return;
			}
			catchChanged = true;
			String str = s.toString();
			int dotIndex = str.indexOf(".");
			if (dotIndex >= 0) {
				String strDecmals = str.substring(dotIndex + 1);
				if (strDecmals.length() > mDecimals) {
					str = str.substring(0, dotIndex + 1 + mDecimals);
					mEditText.setText(str);
					mEditText.setSelection(str.length());
				}
			}
			catchChanged = false;
		}
	}
}
